#include <linux/module.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/msi.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include "drv_di.h"

#define DI_MODE_MASK            0x001C0000      /* DI 模式掩码 */
#define DI_EDGE_MASK            0x00030000      /* DI 边沿掩码 */
#define DI_DELAY_MASK           0x0000FFFF      /* DI 延时掩码 */
#define DI_MODE_SHIFT           18              /* DI 模式偏移 */
#define DI_EDGE_SHIFT           16              /* DI 边沿偏移 */
#define DI_DELAY_SHIFT          0               /* DI 延时偏移 */
#define DI_DEF_MODE             DI_MOD_LEVEL    /* DI 默认模式 */
#define DI_DEF_EDGE             DI_EDGE_RISE    /* DI 默认边沿 */
#define DI_DEF_DELAY            10              /* DI 默认延时, 0~65535us */

#define DI_MSI_MASK             0x01            /* DI MSI 掩码 */
#define DI_MSI_VEC_START        2               /* DI MSI 中断向量起始 */

#define DI_DEF_INIT_LEVEL       0x00000000      /* DI 默认电平 */

/* DI 寄存器*/
enum di_reg_t {
    DI_VERSION_OFFSET           = 0x04,         /* 版本 寄存器 */
    // DI_CMD_OFFSET               = 0x08,         /* DI 指令寄存器偏移 */
    DI_ALL_STA_OFFSET           = 0x30,         /* DI 所有通道状态寄存器偏移 */
    DI_MSI_MASK_OFFSET          = 0x60,         /* DI DMI 屏蔽寄存器偏移 */
    DI_MODE_OFFSET              = 0x6C,         /* DI 模式寄存器偏移 */
    // DI_INIT_VAL_OFFSET          = 0x70,         /* DI 初始值寄存器偏移 */
    DI_ID_OFFSET                = 0x74,         /* DI 通道寄存器偏移 */
    DI_FREQ_OFFSET              = 0x78,         /* DI 通道频率寄存器偏移 */
};

/* 文件操作函数声明 */
static int open_di(struct inode *inode, struct file *filp);
static int release_di(struct inode *inode, struct file *filp);
static long ioctl_di(struct file *filp, unsigned int cmd, 
                     unsigned long arg);

/* 文件操作结构体 */
static const struct file_operations cdev_fops = {
    .owner = THIS_MODULE,
    .open = open_di,
    .release = release_di,
    .read = NULL,
    .write = NULL,
    .unlocked_ioctl = ioctl_di,
    .poll = NULL,
    .llseek = no_llseek,
};

/* 读取 DI 寄存器 */
static u32 read_di_reg_le(struct pcie_dev_t *pcie_dev, u32 reg)
{
    u32 val = 0;
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&pcie_dev->splock, flags);
    val = ioread32(pcie_dev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&pcie_dev->splock, flags);
    pr_debug("%s  reg=0x%08x, val=0x%08x", __func__, reg, val);

    return val;
}

/* 写入 DI 寄存器 */
static void write_di_reg_le(struct pcie_dev_t *pcie_dev, u32 reg, u32 val)
{
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&pcie_dev->splock, flags);
    iowrite32(val, pcie_dev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&pcie_dev->splock, flags);
    pr_debug("%s reg=0x%08x, val=0x%08x", __func__, reg, val);
}

/* 使能 MSI 中断 */
static int enable_di_msi_irq(struct di_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MSI_MASK_OFFSET);
    val |= DI_MSI_MASK;
    pctrl->write_reg(pctrl->pcie_dev, DI_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 禁用 MSI 中断 */
static int disable_di_msi_irq(struct di_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MSI_MASK_OFFSET);
    val &= (~DI_MSI_MASK);
    pctrl->write_reg(pctrl->pcie_dev, DI_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 配置 DI 模式 */
static int set_di_mode(struct di_dev_t *pdev, u8 mode)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    u8 mode_code = mode;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    switch (mode) {
    case DI_MOD_LEVEL:
    // case DI_MOD_FREQ:
    // case DI_MOD_EVENT:
    case DI_MOD_IRQ:
        break;
    default:
        mode_code = DI_DEF_MODE;
        dev_warn(pctrl->dev, "DI %2d mode %d not support, use default %d", pdev->index, mode, mode_code);
        break;
    }
    pdev->mode = mode_code;
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    val &= (~DI_MODE_MASK);
    val |= (mode_code << DI_MODE_SHIFT);
    pctrl->write_reg(pctrl->pcie_dev, DI_MODE_OFFSET, val);
    dev_dbg(pctrl->dev, "Set DI %2d mode %d success", pdev->index, mode_code);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 DI 模式 */
static int get_di_mode(struct di_dev_t *pdev)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pdev->name);
        return -ERESTARTSYS;
    }
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    pdev->mode_get = ((val & DI_MODE_MASK) >> DI_MODE_SHIFT);
    if (pdev->mode_get != pdev->mode) {
        dev_err(pctrl->dev, "Get DI %2d mode %d, not the set %d", pdev->index, pdev->mode_get, pdev->mode);
        ret = -EFAULT;
        goto unlock;
    } else {
        switch (pdev->mode_get) {
        case DI_MOD_LEVEL:
        // case DI_MOD_FREQ:
        // case DI_MOD_EVENT:
        case DI_MOD_IRQ:
            dev_dbg(pctrl->dev, "Get DI %2d mode %d, is the set %d", pdev->index, pdev->mode_get, pdev->mode);
            break;
        default:
            dev_err(pctrl->dev, "Get DI %2d mode %d not support", pdev->index, pdev->mode_get);
            break;
        }
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 DI 边沿 */
static int set_di_edge(struct di_dev_t *pdev, u8 edge)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    u8 edge_code = edge;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    switch (edge) {
    case DI_EDGE_RISE:
    case DI_EDGE_FALL:
    case DI_EDGE_RISE_FALL:
        break;
    default:
        edge_code = DI_DEF_EDGE;
        dev_warn(pctrl->dev, "DI %2d edge %d not support, use default %d", pdev->index, edge, edge_code);
        break;
    }
    pdev->edge = edge_code;
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    val &= (~DI_EDGE_MASK);
    val |= ((edge_code << DI_EDGE_SHIFT) & DI_EDGE_MASK);
    pctrl->write_reg(pctrl->pcie_dev, DI_MODE_OFFSET, val);
    dev_dbg(pctrl->dev, "Set %2d DI edge %d success", pdev->index, edge_code);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 DI 边沿 */
static int get_di_edge(struct di_dev_t *pdev)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    pdev->edge_get = ((val & DI_EDGE_MASK) >> DI_EDGE_SHIFT);
    if (pdev->edge_get != pdev->edge) {
        dev_err(pctrl->dev, "Get %2d DI edge %d, not the set %d", pdev->index, pdev->edge_get, pdev->edge);
        ret = -EFAULT;
        goto unlock;
    } else {
        switch (pdev->edge_get) {
        case DI_EDGE_RISE:
        case DI_EDGE_FALL:
        case DI_EDGE_RISE_FALL:
            dev_dbg(pctrl->dev, "Get %2d DI edge %d, is the set %d", pdev->index, pdev->edge_get, pdev->edge);
            break;
        default:
            dev_err(pctrl->dev, "Get %2d DI edge %d not support", pdev->index, pdev->edge_get);
            break;
        }
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 DI 延时时间 */
static int set_di_delay(struct di_dev_t *pdev, u16 delay)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pdev->delay = delay;
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    val &= (~DI_DELAY_MASK);
    val |= ((delay << DI_DELAY_SHIFT) & DI_DELAY_MASK);
    pctrl->write_reg(pctrl->pcie_dev, DI_MODE_OFFSET, val);
    dev_dbg(pctrl->dev, "Set DI %2d delay %dus success", pdev->index, delay);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 DI 延时时间 */
static int get_di_delay(struct di_dev_t *pdev)
{
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
    val = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
    pdev->delay_get = ((val & DI_DELAY_MASK) >> DI_DELAY_SHIFT);
    if (pdev->delay_get != pdev->delay) {
        dev_err(pctrl->dev, "Get DI %2d delay %dus, not the set %d", pdev->index, pdev->delay_get, pdev->delay);
        ret = -EFAULT;
        goto unlock;
    } else {
        dev_dbg(pctrl->dev, "Get DI %2d delay %dus, is the set %d", pdev->index, pdev->delay_get, pdev->delay);
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

// /* 配置 DI 初始电平 */
// static int set_di_init_level(struct di_ctrl_t *pctrl, u32 level)
// {
//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     pctrl->init_level = level;
//     pctrl->write_reg(pctrl->pcie_dev, DI_INIT_VAL_OFFSET, level);
//     dev_dbg(pctrl->dev, "Set DI init level 0x%08x success", level);
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return 0;
// }

/* 获取 DI 初始电平 */
// static int get_di_init_level(struct di_ctrl_t *pctrl)
// {
//     int ret = 0;

//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     pctrl->init_level_get = pctrl->read_reg(pctrl->pcie_dev, DI_MODE_OFFSET);
//     if (pctrl->init_level_get != pctrl->init_level) {
//         dev_err(pctrl->dev, "Get DI delay %dus, not the set %d", pctrl->init_level_get, pctrl->init_level);
//         ret = -EFAULT;
//         goto unlock;
//     } else {
//         dev_dbg(pctrl->dev, "Get DI delay %dus, is the set %d", pctrl->init_level_get, pctrl->init_level);
//     }

// unlock:
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return ret;
// }

/* 开始 DI 频率测量 */
// static int start_di_capture(struct di_ctrl_t *pctrl)
// {
//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     pctrl->write_reg(pctrl->pcie_dev, DI_CMD_OFFSET, DI_CMD_START);
//     dev_dbg(pctrl->dev, "Start DI freq  success");
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return 0;
// }

/* 获取所有 DI 电平状态 */
static u32 get_all_di_level(struct di_ctrl_t *pctrl)
{
    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->level = pctrl->read_reg(pctrl->pcie_dev, DI_ALL_STA_OFFSET);
    /* 硬件为反逻辑，须软件反转电平 */
    pctrl->level = ~pctrl->level;
    dev_dbg(pctrl->dev, "Get all DI level 0x%08x", pctrl->level);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return pctrl->level;
}

/* 获取 DI 频率值 */
// static u32 get_di_freq(struct di_dev_t *pdev)
// {
//     struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(pdev->parent);
//     u32 val = 0;

//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     pctrl->write_reg(pctrl->pcie_dev, DI_ID_OFFSET, pdev->index);
//     val = pctrl->read_reg(pctrl->pcie_dev, DI_FREQ_OFFSET);
//     dev_dbg(pctrl->dev, "Get DI%d freq %d", pdev->index, val);
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return 0;
// }

/* 打开设备 */
static int open_di(struct inode *inode, struct file *filp)
{
    /* 获取与 inode 关联的字符设备 */
    struct cdev_dev_t *cdev_dev = container_of(inode->i_cdev, struct cdev_dev_t, cdev);
    struct cdev_ctrl_t *cdev_ctrl = (struct cdev_ctrl_t *)(cdev_dev->parent);
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(cdev_ctrl->parent);
    struct di_dev_t *priv = &pctrl->di[cdev_dev->index];

    /* 检查设备是否有效 */
    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }
    /* 记录设备指针 */
    filp->private_data = priv;
    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire DI %2d mutex failed", cdev_dev->index);
        return -ERESTARTSYS;
    }
    dev_dbg(priv->dev, "Open DI %2d device", cdev_dev->index);

    mutex_unlock(&priv->lock);

    return 0;
}

/* 关闭设备 */
static int release_di(struct inode *inode, struct file *filp)
{
    struct di_dev_t *priv = filp->private_data;

    if (priv) {
        mutex_lock(&priv->lock);
        dev_dbg(priv->dev, "Release DI %2d device", priv->index);
        mutex_unlock(&priv->lock);
    }

    return 0;
}

/* IOCTL 处理 */
static long ioctl_di(struct file *filp, unsigned int cmd, 
                          unsigned long arg)
{
    struct di_dev_t *priv = filp->private_data;
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(priv->parent);
    long ret = 0;
    u8 u8_val = 0;
    u16 u16_val = 0;

    /* 检查参数是否有效 */
    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire DI %2d mutex failed", priv->index);
        return -ERESTARTSYS;
    }
    switch (cmd) {
    /* 配置 DI 模式 */
    case IOCTL_DI_SET_MODE:
        if (copy_from_user(&u8_val, (void __user *)arg, sizeof(u8_val))) {
            dev_err(priv->dev, "Set DI %2d mode failed", priv->index);
            ret = -EFAULT;
            goto unlock;
        }
        if (set_di_mode(priv, u8_val) < 0) {
            dev_err(priv->dev, "Set DI %2d mode %d failed", priv->index, u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 DI 模式 */
    case IOCTL_DI_CHK_MODE:
        if (get_di_mode(priv) < 0) {
            dev_err(priv->dev, "Get DI %2d mode %d failed", priv->index, priv->mode_get);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &priv->mode_get, sizeof(priv->mode_get))) {
            dev_err(priv->dev, "Get DI %2d mode %d copy failed", priv->index, priv->mode_get);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 DI 边沿 */
    case IOCTL_DI_SET_EDGE:
        if (copy_from_user(&u8_val, (void __user *)arg, sizeof(u8_val))) {
            dev_err(priv->dev, "Set DI %2d edge failed", priv->index);
            ret = -EFAULT;
            goto unlock;
        }
        if (set_di_edge(priv, u8_val) < 0) {
            dev_err(priv->dev, "Set DI %2d edge %d failed", priv->index, u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 DI 边沿 */
    case IOCTL_DI_CHK_EDGE:
        if (get_di_edge(priv) < 0) {
            dev_err(priv->dev, "Get DI %2d edge %d failed", priv->index, priv->edge_get);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &priv->edge_get, sizeof(priv->edge_get))) {
            dev_err(priv->dev, "Get DI %2d edge %d copy failed", priv->index, priv->edge_get);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 DI 滤波时间 */
    case IOCTL_DI_SET_FILTER:
        if (copy_from_user(&u16_val, (void __user *)arg, sizeof(u16_val))) {
            dev_err(priv->dev, "Set DI %2d delay failed", priv->index);
            ret = -EFAULT;
            goto unlock;
        }
        if (set_di_delay(priv, u16_val) < 0) {
            dev_err(priv->dev, "Set DI %2d delay %dus failed", priv->index, u16_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 DI 滤波时间 */
    case IOCTL_DI_CHK_FILTER:
        if (get_di_delay(priv) < 0) {
            dev_err(priv->dev, "Get DI %2d delay %d failed", priv->index, priv->delay_get);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &priv->delay_get, sizeof(priv->delay_get))) {
            dev_err(priv->dev, "Get DI %2d delay %d copy failed", priv->index, priv->delay_get);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 DI 初始电平 */
    // case IOCTL_DI_SET_INIT_LEVEL:
    //     if (copy_from_user(&u32_val, (void __user *)arg, sizeof(u32_val))) {
    //         dev_err(priv->dev, "Set DI init level failed");
    //         ret = -EFAULT;
    //         goto unlock;
    //     }
    //     if (set_di_init_level(pctrl, u32_val) < 0) {
    //         dev_err(priv->dev, "Set DI init level 0x%08x failed", u32_val);
    //         ret = -EFAULT;
    //         goto unlock;
    //     }
    //     break;
    /* 获取 DI 初始电平 */
    // case IOCTL_DI_GET_INIT_LEVEL:
    //     if (get_di_init_level(pctrl) < 0) {
    //         dev_err(priv->dev, "Get DI init level %d failed", pctrl->init_level_get);
    //         ret = -EFAULT;
    //         goto unlock;
    //     }
    //     if (copy_to_user((void __user *)arg, &pctrl->init_level_get, sizeof(pctrl->init_level_get))) {
    //         dev_err(priv->dev, "Get DI init level %d copy failed", pctrl->init_level_get);
    //         ret = -EFAULT;
    //         goto unlock;
    //     }
    //     break;
    /* 开始 DI 频率采集 */
    // case IOCTL_DI_START_CAP:
    //     if (start_di_capture(pctrl) < 0) {
    //         dev_err(priv->dev, "Start DI capture failed");
    //         ret = -EFAULT;
    //         goto unlock;
    //     }
    //     break;
    /* 获取 DI 电平 */
    case IOCTL_DI_GET_LEVEL:
        pctrl->level = get_all_di_level(pctrl);
        u8_val = ((pctrl->level >> priv->index) & 0x01);

        if (copy_to_user((void __user *)arg, &u8_val, sizeof(u8_val))) {
            dev_err(priv->dev, "Get DI %2d data %d copy failed", priv->index, u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    case IOCTL_DI_WAIT_IRQ:
        mutex_unlock(&priv->lock);
        dev_dbg(priv->dev, "Wait DI %2d edge...", priv->index);
        /* 等待边沿队列(可中断唤醒) */
        if (wait_event_interruptible(priv->edge_wq, priv->cap_edge)) {
            dev_err(priv->dev, "Wait DI %2d edge interrupted", priv->index);
            return -ERESTARTSYS;
        }
        priv->cap_edge = false;
        dev_dbg(priv->dev, "Capture DI %2d edge", priv->index);

        /* 获取互斥锁 */
        if (mutex_lock_interruptible(&priv->lock)) {
            dev_err(priv->dev, "Acquire DI %2d mutex failed", priv->index);
            return -ERESTARTSYS;
        }
        pctrl->level = get_all_di_level(pctrl);
        u8_val = ((pctrl->level >> priv->index) & 0x01);

        if (copy_to_user((void __user *)arg, &u8_val, sizeof(u8_val))) {
            dev_err(priv->dev, "Get DI %2d data %d failed", priv->index, u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取驱动版本号 */
    case IOCTL_DI_GET_DRV_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->drv_ver, sizeof(pctrl->drv_ver))) {
            dev_err(pctrl->dev, "Get DI driver version %d copy failed", pctrl->drv_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 FPGA 版本号 */
    case IOCTL_DI_GET_FPGA_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->fpga_ver, sizeof(pctrl->fpga_ver))) {
            dev_err(pctrl->dev, "Get DI FPGA version %d copy failed", pctrl->fpga_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    default:
        dev_err(priv->dev, "Ioctl DI %2d cmd=0x%08x, dir=0x%X, size=%u, type=0x%02X('%c'), nr=%u not support\n",
                priv->index, cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd), _IOC_TYPE(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd));
        ret = -ENOTTY;
        break;
    }

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

/* DI 中断 */
static irqreturn_t di_interrupt(int irq, void *dev_id)
{
    struct di_dev_t *priv = dev_id;
    struct di_ctrl_t *pctrl = (struct di_ctrl_t *)(priv->parent);

    if (!priv || !priv->dev || !pctrl) {
        pr_err("Invalid parameters for %s, %p, %p, %p", 
               __func__, priv, priv->dev, pctrl);
        return IRQ_NONE;
    }
    dev_dbg(priv->dev, "IRQ: %s DI %2d irq %d", priv->name, priv->index, irq);

    disable_di_msi_irq(pctrl);
    priv->cap_edge = true;
    wake_up_interruptible(&priv->edge_wq);      /* 唤醒等待队列 */
    enable_di_msi_irq(pctrl);

    return IRQ_HANDLED;
}

/* 初始化 DI 设备 */
static int init_di_dev(void *parent, struct device *dev, const char *name, 
                       struct di_dev_t *di, u8 index)
{
    int ret = 0;

    di->parent = parent;
    di->dev = dev;
    /* 初始化互斥锁 */
    mutex_init(&di->lock);
    strscpy(di->name, name, sizeof(di->name));
    di->index = index;
    set_di_mode(di, DI_DEF_MODE);       /* 配置 DI 模式 */
    set_di_edge(di, DI_DEF_EDGE);       /* 配置 DI 边沿 */
    set_di_delay(di, DI_DEF_DELAY);     /* 配置 DI 延时时间 */

    /* 初始化 边沿 等待队列 */
    init_waitqueue_head(&di->edge_wq);

    return ret;
}

/* 初始化 DI 控制器 */
int init_di_ctrl(struct pcie_dev_t *pcie_dev, struct cdev_dev_t *cdev_dev, 
                 struct di_ctrl_t *pctrl, struct di_dev_t *di, 
                 const char *ctrl_name, u8 dev_num)
{
    int ret = 0;
    int i = 0;
    char name[32];

    pctrl->dev = &pcie_dev->pdev->dev;
    /* 初始化互斥锁 */
    mutex_init(&pctrl->lock);
    snprintf(pctrl->name, sizeof(pctrl->name), "%s", ctrl_name);
    pctrl->num = dev_num;
    pctrl->pcie_dev = pcie_dev;
    pctrl->read_reg = read_di_reg_le;
    pctrl->write_reg = write_di_reg_le;
    pctrl->cdev_ctrl.cdev_dev = cdev_dev;
    pctrl->di = di;
    pctrl->drv_ver = CDEV_DRV_VERSION(DI_VER_MAJOR, DI_VER_MINOR, DI_VER_PATCH);
    pctrl->fpga_ver = pcie_dev->read_mem(pcie_dev->bar[0] + DI_VERSION_OFFSET);

    /* 初始化中断 */
    enable_di_msi_irq(pctrl);
    pctrl->irq_ctrl.irq = &pcie_irq;
    ret = init_pcie_irq(pctrl->pcie_dev->pdev, &pctrl->irq_ctrl, 
                        PCI_IRQ_MSI, DI_MSI_VEC_START, (DI_MSI_VEC_START + dev_num - 1), 
                        di_interrupt, pctrl->name,
                        pctrl->di, sizeof(struct di_dev_t), pctrl->pcie_dev->bar[0]);
    if (ret) {
        dev_err(pctrl->dev, "Init %s pcie interrupt failed", pctrl->name);
        goto err_free_dev;
    }

    /* 初始化字符设备 */
    ret = init_cdev_ctrl(pctrl, &pctrl->cdev_ctrl, pctrl->name, dev_num);
    if (ret < 0) {
        dev_err(pctrl->dev, "Init %s controller failed", pctrl->name);
        goto err_cleanup_irq;
    }
    for (i = 0; i < dev_num; i++) {
        snprintf(name, sizeof(name), "%s%d", pctrl->name, i);
        ret = init_cdev_dev(&pctrl->cdev_ctrl, pctrl->cdev_ctrl.cclass, 
                            &pctrl->cdev_ctrl.cdev_dev[i], &cdev_fops, pctrl->cdev_ctrl.major_devno, name, i);
        if (ret) {
            dev_err(pctrl->dev, "Init %s device failed", name);
            goto err_cleanup_cdev_ctrl;
        }
    }

    /* 初始化 DI 设备*/
    // set_di_init_level(pctrl, DI_DEF_INIT_LEVEL);     /* 配置 DI 初始电平 */
    // start_di_capture(pctrl);                         /* 开始 DI 频率采集 */
    for (i = 0; i < dev_num; i++) {
        init_di_dev(pctrl, pctrl->dev, pctrl->cdev_ctrl.cdev_dev[i].name, 
                    &pctrl->di[i], i);
    }

    return 0;

err_cleanup_cdev_ctrl:
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
err_cleanup_irq:
    exit_pcie_irq(&pctrl->irq_ctrl, pctrl->di, sizeof(struct di_dev_t));
err_free_dev:

    return ret;
}

/* 注销 DI 控制器 */
void exit_di_ctrl(struct di_ctrl_t *pctrl, u8 dev_num)
{
    u8 i = 0;

    if (!pctrl) {
        pr_err("Invalid parameters for %s", __func__);
        return;
    }

    for (i = 0; i < dev_num; i++) {
        exit_cdev_dev(pctrl->cdev_ctrl.cclass, &pctrl->cdev_ctrl.cdev_dev[i]);
    }
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
    dev_info(pctrl->dev, "Release cdev controller success");

    exit_pcie_irq(&pctrl->irq_ctrl, pctrl->di, sizeof(struct di_dev_t));
    dev_info(pctrl->dev, "Release irq controller success");

    for (i = 0; i < dev_num; i++) {
        mutex_destroy(&pctrl->di[i].lock);
    }
    /* 注销互斥锁 */
    mutex_destroy(&pctrl->lock);

    dev_info(pctrl->dev, "PCIe character device %s removed", pctrl->name);
}
